package com.gamesite.gamesite.core.socket;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gamesite.gamesite.core.pojo.GameRoom;
import com.gamesite.gamesite.core.pojo.User;
import com.gamesite.gamesite.core.service.UserService;
import com.gamesite.gamesite.core.vo.RoomPlayerVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;

@Component
@ServerEndpoint("/ws/gameRoom")
public class WsGameRoomEndpoint {
    private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<>());
    private static final Map<Long, GameRoom> roomList = new HashMap<>();
    private static final Map<Session, User> userMap = new HashMap<>();


    private static UserService userService;

    @Autowired
    public void initWsGameRoomEndpoint(UserService userService) {
        WsGameRoomEndpoint.userService = userService;
    }

    @OnOpen
    public void onOpen(Session session) throws IOException {
        sessions.add(session);
        System.out.println("Connected: " + session.getId());

    }

    @OnMessage
    public void onMessage(String message, Session session) {
        System.out.println("Message from " + session.getId() + ": " + message);
        try {
            // 解析消息
            JSONObject jsonMessage = JSONObject.parseObject(message);
            String type = jsonMessage.getString("type");

            switch (type) {
                case "setId":
                    bindSessionUserInfo(session, jsonMessage);
                    break;
                case "createRoom":
                    handleCreateRoom(jsonMessage, session);
                    break;
                case "joinRoom":
                    handleJoinRoom(jsonMessage, session);
                    break;
                case "getRoom":
                    handleGetRoom(jsonMessage, session);
                    break;
                case "leaveRoom":
                    handleLeaveRoom(jsonMessage, session);
                    break;
                case "startGame":
                    handleStartGame(jsonMessage, session);
                    break;
                case "ping":
                    System.out.println("Received ping from " + session.getId());
                    pong(session);
                    break;
                default:
                    System.out.println("未知消息类型: " + type);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 通知房间内的每一个玩家游戏开始
    private void handleStartGame(JSONObject jsonMessage, Session session) {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> messageReturn = new HashMap<>();
        Long roomId = jsonMessage.getLong("roomId");
        String gameId = jsonMessage.getString("gameId");
        if (roomList.containsKey(roomId)) {
            GameRoom room = roomList.get(roomId);
            room.setIsStart(true);
            messageReturn.put("type", "gameStarted");
            messageReturn.put("roomId", room.getRoomId());
            messageReturn.put("gameId", gameId);
            messageReturn.put("message", "游戏开始了！");
            try {
                String jsonData = objectMapper.writeValueAsString(messageReturn);
                for (RoomPlayerVo player : room.getPlayerList()) {
                    Session playerSession = getUserSessionByUserId(player.getId());
                    if (playerSession != null && playerSession.isOpen()) {
                        playerSession.getBasicRemote().sendText(jsonData);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("房间不存在，无法开始游戏");
        }

    }


    @OnClose
    public void onClose(Session session) {
        sessions.remove(session);
        removeSessionUserInfo(session);
        System.out.println("Disconnected: " + session.getId());

        // 移除断开连接的用户
        for (GameRoom room : roomList.values()) {
            Iterator<RoomPlayerVo> iterator = room.getPlayerList().iterator();
            while (iterator.hasNext()) {
                RoomPlayerVo player = iterator.next();
                if (player.getId().equals(session.getId())) {
                    iterator.remove();
                    break;
                }
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable error) {
        error.printStackTrace();
    }


    // 绑定用户信息到session
    private void bindSessionUserInfo(Session session, JSONObject jsonMessage) {
        // 从数据库中获取用户信息
        Integer userId = Integer.parseInt(jsonMessage.getString("userId"));
        User user = userService.getById(userId);
        if (user != null) { // 确保用户对象不为null
            userMap.put(session, user);
        } else {
            System.err.println("User not found with ID: " + userId);
        }
    }
    //删除用户信息
    private void removeSessionUserInfo(Session session) {
        userMap.remove(session);
    }

    // 生成六位房间号 如果已存在则重新生成
    private Long generateUniqueRoomId() {
        Random random = new Random();
        Long roomId;
        do {
            roomId = 100000L + random.nextInt(900000);
        } while (roomList.containsKey(roomId));
        return roomId;
    }
    // 处理创建房间请求
    private void handleCreateRoom(JSONObject jsonMessage, Session session) throws IOException {
        bindSessionUserInfo(session,jsonMessage);
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> messageReturn = new HashMap<>();
        // 随机生成六位房间号
        Long roomId = jsonMessage.getLong("roomId");
        if (roomId == null) {
            roomId = generateUniqueRoomId();
        }
        // 创建房间 添加到房间列表
        if (!roomList.containsKey(roomId)) {
            GameRoom newRoom = new GameRoom();
            newRoom.setRoomId(roomId);

            // 设置房间未开始
            newRoom.setIsStart(false);
            roomList.put(roomId, newRoom);
            //
            // 获取用户信息
            List<RoomPlayerVo> playerList = new ArrayList<>();
            RoomPlayerVo player = new RoomPlayerVo(userService.getById(Long.parseLong(jsonMessage.getString("userId"))));
            //设置该用户为房主
            player.setStatus("host");
            //如果list中没有该用户，则添加
            if (!playerList.contains(player)) {
                playerList.add(player);
            }
            newRoom.setPlayerList(playerList);

            messageReturn.put("type", "roomCreated");
            messageReturn.put("roomId", roomId);
            messageReturn.put("message", "成功创建房间");


        } else {
            messageReturn.put("type", "error");
            messageReturn.put("message", "房间已存在");

        }
        String jsonData = objectMapper.writeValueAsString(messageReturn);
        session.getBasicRemote().sendText(jsonData);

        System.out.println("User " + session.getId() + " created room " + roomId);
        System.out.println("Room " + roomId + " playerList: " + roomList.get(roomId).getPlayerList());
    }

    private void handleJoinRoom(JSONObject jsonMessage, Session session) throws IOException {
        bindSessionUserInfo(session,jsonMessage);
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> messageReturn = new HashMap<>();
        Long roomId = jsonMessage.getLong("roomId");
        if (roomList.containsKey(roomId)) {
            GameRoom room = roomList.get(roomId);

            // 获取新加入的玩家信息并添加到房间列表中
            RoomPlayerVo player = new RoomPlayerVo(userService.getById(Long.parseLong(jsonMessage.getString("userId"))));
            if (!room.getPlayerList().contains(player)) {
                room.getPlayerList().add(player);
            }


            // 构建返回的消息
            messageReturn.put("type", "roomJoined");
            messageReturn.put("roomId", room.getRoomId());
            messageReturn.put("message", "成功加入房间");

            // 将更新后的房间信息发送给房间内所有玩家
            sendRoomUpdateToAllPlayers(room);
        } else {
            messageReturn.put("type", "error");
            messageReturn.put("message", "房间不存在");
        }
        String jsonData = objectMapper.writeValueAsString(messageReturn);
        session.getBasicRemote().sendText(jsonData);

        System.out.println("User " + session.getId() + " joined room " + roomId);
        System.out.println("Room " + roomId + " playerList: " + roomList.get(roomId).getPlayerList());
    }

    /**
     * 发送房间更新消息给房间内的所有玩家。
     */
    private void sendRoomUpdateToAllPlayers(GameRoom room) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> messageReturn = new HashMap<>();
        messageReturn.put("type", "roomUpdate");
        messageReturn.put("roomId", room.getRoomId());
        messageReturn.put("playerList", room.getPlayerList());
        messageReturn.put("message", "房间信息已更新");

        String jsonData = objectMapper.writeValueAsString(messageReturn);

        for (RoomPlayerVo player : room.getPlayerList()) {
            Session playerSession = getUserSessionByUserId(player.getId());
            if (playerSession != null && playerSession.isOpen()) {
                playerSession.getBasicRemote().sendText(jsonData);
            }
        }
    }

    /**
     * 根据用户ID获取对应的session。
     */
    private Session getUserSessionByUserId(Long userId) {
        for (Map.Entry<Session, User> entry : userMap.entrySet()) {
            if (entry.getValue() != null && userId.equals(entry.getValue().getId())) {
                return entry.getKey();
            }
        }
        return null;
    }
    private void handleLeaveRoom(JSONObject jsonMessage, Session session) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> messageReturn = new HashMap<>();

        Long roomId = jsonMessage.getLong("roomId");
        Long userId = Long.parseLong(jsonMessage.getString("userId"));

        if (roomList.containsKey(roomId)) {
            GameRoom room = roomList.get(roomId);
            RoomPlayerVo player = new RoomPlayerVo();
            //根据userId从room的playerList中查找player
            for (RoomPlayerVo p : room.getPlayerList()) {
                if (p.getId().equals(userId)) {
                    player = p;
                    break;
                }
            }
            //如果退出的玩家为host则解散房间并将该房间所有玩家都移除 如果不是host则从房间列表中移除该玩家
            if (player.getStatus().equals("host")) {
                GameRoom room1 = roomList.get(roomId);
                //将房间内所有玩家移除
                for (RoomPlayerVo p : room1.getPlayerList()) {
                    Session playerSession = getUserSessionByUserId(p.getId());
                    if (playerSession != null && playerSession.isOpen()) {
                        messageReturn.put("type", "roomDisbanded");
                        messageReturn.put("roomId", roomId);
                        messageReturn.put("message", "房间已解散。");
                        String jsonData = objectMapper.writeValueAsString(messageReturn);
                        playerSession.getBasicRemote().sendText(jsonData);
                    }
                }
                roomList.remove(roomId);
                return;
            } else {
                room.getPlayerList().remove(player);
                messageReturn.put("type", "playerLeft");
                messageReturn.put("roomId", roomId);
                messageReturn.put("message", "玩家已离开房间。");
                // 将更新后的房间信息发送给房间内所有玩家
                sendRoomUpdateToAllPlayers(room);
            }
        } else {
            messageReturn.put("type", "error");
            messageReturn.put("message", "房间不存在");
        }
        String jsonData = objectMapper.writeValueAsString(messageReturn);
        session.getBasicRemote().sendText(jsonData);

        System.out.println("User " + session.getId() + " left room " + roomId);
    }

    private void handleGetRoom(JSONObject jsonMessage, Session session) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, Object> messageReturn = new HashMap<>();
        Long roomId = jsonMessage.getLong("roomId");

        if (roomList.containsKey(roomId)) {
            GameRoom room = roomList.get(roomId);
            messageReturn.put("type", "roomUpdate");
            messageReturn.put("roomId", room.getRoomId());
            messageReturn.put("playerList", room.getPlayerList());
            messageReturn.put("message", "房间信息已更新");
        } else {
            messageReturn.put("type", "error");
            messageReturn.put("message", "房间不存在");
        }

        String jsonData = objectMapper.writeValueAsString(messageReturn);
        session.getBasicRemote().sendText(jsonData);
        System.out.println("User " + session.getId() + " requested room " + roomId);
        System.out.println("Room " + roomId + " playerList: " + roomList.get(roomId).getPlayerList());
    }

    private Session getUserSessionById(String sessionId) {
        for (Session session : sessions) {
            if (session.getId().equals(sessionId)) {
                return session;
            }
        }
        return null;
    }
    private void pong(Session session) throws IOException {
        System.out.println("Sending pong to " + session.getId());
        JSONObject pongMessage = new JSONObject();
        pongMessage.put("type", "pong");

        session.getBasicRemote().sendText(pongMessage.toString());
    }

}
